# coding=utf-8
import json
from operator import itemgetter

import jieba

from util import stopword
from util.tiny_tool import *

d = 0.85
max_iter = 30
min_diff = 0.0001


def vote_from_neiber(token, score_old, neighbor_dic):
    """
    邻居给某一个词更新 TextRank 分数
    :param token: 
    :param score_old: 
    :param neighbor_dic: 
    :return: 
    """
    sum_other = 0.0
    for other in neighbor_dic[token]:
        other_len = len(neighbor_dic[other])
        sum_other += d / other_len * score_old

    return 1 - d + sum_other


def cut_to_list(input_str):
    """
    将输入的语句进行分词
    :param input_str: 
    :return: 
    """
    input_cut_result = jieba.cut(input_str)
    token_list = []
    for token in input_cut_result:
        if not stopword.has_key(token):  # 自己封装的判断是否停用词方法，在stopword/stopword.py
            token_list.append(token)

    return token_list


def calc_neighbor_dic(token_list):
    """
    构造词邻居矩阵
    :param token_list: 已分好的词列表
    :return: 
    """
    neighbor_dic = {}
    index = 0
    start_index = 0
    end_index = 0
    token_list_len = len(token_list)
    window_size = 5
    for index, token in enumerate(token_list):
        start_index = index - (window_size - 1) if index > (window_size - 1) else 0
        end_index = index + (window_size - 1) if index < token_list_len - 1 else token_list_len - 1
        neibor_list = list(set(token_list[start_index:index] + token_list[index + 1:end_index]))
        neighbor_dic[token] = neibor_list

    print_title('邻居矩阵')
    for key, value in neighbor_dic.items():
        print key,
        print json.dumps(value, encoding='UTF-8', ensure_ascii=False)
    return neighbor_dic


def iter_vote(token_list, neighbor_dic):
    """
    迭代投票
    不断更新 TextRank 分数
    :param token_list: 
    :param neighbor_dic: 
    :return: 
    """
    score_dic = {}
    i = 0
    print_title('迭代开始...')
    while i < max_iter:
        max_diff = 0.0
        for token in token_list:
            score_old = score_dic.get(token, 0)
            score_new = vote_from_neiber(token, score_old, neighbor_dic)
            score_dic[token] = score_new
            max_diff = max(max_diff, abs(score_new - score_old))
        i += 1
        if max_diff <= min_diff:  # 使用两次迭代误差极小，判断收敛
            break
    print_title('迭代结束...')

    return score_dic


if __name__ == '__main__':
    # input_str = '程序员(英文Programmer)是从事程序开发、维护的专业人员。一般将程序员分为程序设计人员和程序编码人员，但两者的界限并不非常清楚，特别是在中国。软件从业人员分为初级程序员、高级程序员、系统分析员和项目经理四大类。'
    input_str = 'TextRank是在Google的PageRank算法启发下，针对文本里的句子设计的权重算法，目标是自动摘要。它利用投票的原理，让每一个单词给它的邻居（术语称窗口）投赞成票，票的权重取决于自己的票数。这是一个“先有鸡还是先有蛋”的悖论，PageRank采用矩阵迭代收敛的方式解决了这个悖论'
    token_list = cut_to_list(input_str)
    neighbor_dic = calc_neighbor_dic(token_list)
    score_dic = iter_vote(token_list, neighbor_dic)

    print_title('分数矩阵')
    score_tuple = sorted(score_dic.iteritems(), key=itemgetter(1), reverse=True)
    for value in score_tuple:
        print value[0], value[1]
